#include "tju_tcp.h"

/*
创建 TCP socket
初始化对应的结构体
设置初始状态为 CLOSED
*/
tju_tcp_t *tju_socket()
{
    init_log();
    gettimeofday(&start, NULL);
    signal(SIGALRM, timeout_handler);

    tju_tcp_t *sock = (tju_tcp_t *)malloc(sizeof(tju_tcp_t));
    sock->state = CLOSED;

    // 初始化发送缓冲区相关变量和锁
    pthread_mutex_init(&(sock->send_lock), NULL);
    sock->sending_buf = (char *)malloc(MAX_BUF_SIZE);
    sock->sending_len = 0;
    sock->send_cleaned_len = 0; // 用于继承之前的seq

    // 初始化接收缓冲区相关变量和锁
    pthread_mutex_init(&(sock->recv_lock), NULL);
    sock->received_buf = (char *)malloc(MAX_BUF_SIZE);
    sock->received_len = 0;
    sock->recv_cleaned_len = 0;

    // 初始化条件变量
    if (pthread_cond_init(&sock->wait_cond, NULL) != 0)
    {
        perror("条件变量初始化失败\n");
        exit(-1);
    }

    // 初始化发送窗口
    sock->window.wnd_send = (sender_window_t *)malloc(sizeof(sender_window_t));
    sock->window.wnd_send->window_size = MAX_DLEN; // 发送窗口大小 swnd = min(cwnd, rwnd)
    sock->window.wnd_send->base = 1;               // 已发送但未收到ack的第一个数据序号（数据从1开始）
    sock->window.wnd_send->ack_cnt = 0;            // 最后收到的ack序号
    sock->window.wnd_send->nextseq = 1;            // 下一个要发送的数据序号
    sock->window.wnd_send->same_ack_cnt = 0;       // 连续收到相同ack的次数，用于快速重传
    sock->window.wnd_send->is_estimating_RTT = FALSE;
    sock->window.wnd_send->SRTT = 200000; // 平滑往返时间初始值
    sock->window.wnd_send->dev_rtt = 0;
    sock->window.wnd_send->timeout.it_value.tv_sec = 0;
    sock->window.wnd_send->timeout.it_value.tv_usec = 200000; // 超时时间初始值
    sock->window.wnd_send->timeout.it_interval.tv_sec = 0;
    sock->window.wnd_send->timeout.it_interval.tv_usec = 0;
    sock->window.wnd_send->congestion_status = SLOW_START; // 拥塞控制状态初始为慢启动
    sock->window.wnd_send->cwnd = MAX_DLEN;                // 拥塞窗口初始值
    sock->window.wnd_send->ssthresh = MAX_BUF_SIZE / 2;    // 慢启动阈值
    sock->window.wnd_send->rwnd = MAX_BUF_SIZE;            // 接收方窗口大小

    // 初始化接收窗口
    sock->window.wnd_recv = (receiver_window_t *)malloc(sizeof(receiver_window_t));
    sock->window.wnd_recv->expect_seq = 1;                    // 期望接收的数据序号
    sock->window.wnd_recv->wnd_available_size = MAX_BUF_SIZE; // 接收窗口可用大小

    sock->packet_FIN = NULL;

    return sock;
}

/*
绑定监听的地址（包括IP和端口）
*/
int tju_bind(tju_tcp_t *sock, tju_sock_addr bind_addr)
{
    sock->bind_addr = bind_addr;
    return 0;
}

/*
被动打开，监听绑定的地址和端口
设置socket的状态为LISTEN
注册该socket到内核的监听socket哈希表
*/
int tju_listen(tju_tcp_t *sock)
{
    init_queue();
    sock->state = LISTEN;
    int hashval = cal_hash(sock->bind_addr.ip, sock->bind_addr.port, 0, 0);
    listen_socks[hashval] = sock;
    return 0;
}

/*
接受连接
返回与客户端通信用的socket
该socket已完成三次握手建立连接
*/
tju_tcp_t *tju_accept(tju_tcp_t *listen_sock)
{
    // 从全连接队列中获取socket（队列为空时阻塞）
    tju_tcp_t *accept_socket = get_from_full();
    printf("从全连接队列中取出一个socket\n");

    tju_tcp_t *new_conn = accept_socket;
    if (new_conn == NULL)
    {
        printf("accept取出失败\n");
        exit(-1);
    }

    // 将新连接放入已建立连接的socket哈希表中
    int hashval = cal_hash(new_conn->established_local_addr.ip, new_conn->established_local_addr.port,
                           new_conn->established_remote_addr.ip, new_conn->established_remote_addr.port);
    established_socks[hashval] = new_conn;

    printf("服务器三次握手完成\n");

    // 创建发送线程
    pthread_t sending_thread_id = 555;
    int rst1 = pthread_create(&sending_thread_id, NULL, sending_thread, (void *)new_conn);
    if (rst1 < 0)
    {
        printf("发送线程创建失败\n");
        exit(-1);
    }
    printf("发送线程创建成功\n");

    // 创建重传线程
    pthread_t retrans_thread_id = 556;
    int rst2 = pthread_create(&retrans_thread_id, NULL, retrans_thread, (void *)new_conn);
    if (rst2 < 0)
    {
        printf("重传线程创建失败\n");
        exit(-1);
    }
    printf("重传线程创建成功\n");

    return new_conn;
}

/*
连接到服务端
函数正常返回后，该socket已完成三次握手建立连接
*/
int tju_connect(tju_tcp_t *sock, tju_sock_addr target_addr)
{
    sock->established_remote_addr = target_addr;

    // 设置本地地址（随机分配可用端口）
    tju_sock_addr local_addr;
    local_addr.ip = inet_network(CLIENT_IP);
    local_addr.port = generate_port();
    sock->established_local_addr = local_addr;

    // 发送SYN包开始三次握手
    uint32_t seq = CLIENT_ISN;
    uint32_t ack = 0;
    char *packet_SYN = create_packet_buf(sock->established_local_addr.port, sock->established_remote_addr.port, seq, ack,
                                         DEFAULT_HEADER_LEN, DEFAULT_HEADER_LEN, SYN_FLAG_MASK, 1, 0, NULL, 0);
    sendToLayer3(packet_SYN, DEFAULT_HEADER_LEN);
    sock->state = SYN_SENT;
    printf("客户端发送SYN包，开始第一次握手\n");

    // 将socket加入已建立连接哈希表（用于后续处理）
    int hashval = cal_hash(local_addr.ip, local_addr.port, target_addr.ip, target_addr.port);
    established_socks[hashval] = sock;

    // 等待连接建立，超时重传SYN包
    struct timeval start, current;
    long timeout = 3; // 超时时间为3秒
    gettimeofday(&start, NULL);
    while (sock->state != ESTABLISHED)
    {
        gettimeofday(&current, NULL);
        long elapsed = (current.tv_sec - start.tv_sec) +
                       (current.tv_usec - start.tv_usec) / 1000000.0;
        if (elapsed > timeout)
        {
            // 超时重传SYN包
            printf("超时重传SYN包\n");
            sendToLayer3(packet_SYN, DEFAULT_HEADER_LEN);
            gettimeofday(&start, NULL);
        }
    }

    free(packet_SYN);
    printf("客户端三次握手完成\n");

    // 创建发送线程
    pthread_t sending_thread_id = 557;
    int rst1 = pthread_create(&sending_thread_id, NULL, sending_thread, (void *)sock);
    if (rst1 < 0)
    {
        perror("发送线程创建失败\n");
        exit(-1);
    }
    printf("发送线程创建成功\n");

    // 创建重传线程
    pthread_t retrans_thread_id = 558;
    int rst2 = pthread_create(&retrans_thread_id, NULL, retrans_thread, (void *)sock);
    if (rst2 < 0)
    {
        perror("重传线程创建失败\n");
        exit(-1);
    }
    printf("重传线程创建成功\n");

    return 0;
}

// 测试中一次性发10KB的数据，会调用该函数5000次
// 把要发送的数据放入发送缓冲区
int tju_send(tju_tcp_t *sock, const void *buffer, int len)
{
    // 因为buffer和len在发送过程中会改变,所以用新的变量
    char *data_buffer = (char *)buffer;
    int data_len = len;
    printf("调用 tju_send()\n");

    // 处理所有待发送数据
    while (data_len)
    {
        // 计算发送缓冲区剩余空间
        uint32_t send_buf_remaining = MAX_BUF_SIZE - (sock->sending_len - sock->send_cleaned_len);

        // 发送缓冲区有足够空间放入数据
        if (data_len <= send_buf_remaining)
        {
            // 发送缓冲区现存数据长度
            uint32_t send_buf_exist_len = sock->sending_len - sock->send_cleaned_len;
            pthread_mutex_lock(&sock->send_lock);
            memcpy(sock->sending_buf + send_buf_exist_len, data_buffer, data_len);
            sock->sending_len += data_len; // 更新发送缓冲区长度
            pthread_mutex_unlock(&sock->send_lock);
            data_len = 0;
            printf("将数据放入发送缓冲区\n");
            break;
        }
        // 如果缓冲区空间不足就等待缓冲区清除
    }
    return 0;
}

// 从接收缓冲区读取数据
int tju_recv(tju_tcp_t *sock, void *buffer, int len)
{
    // 等待接收缓冲区有数据可读
    while ((sock->received_len - sock->recv_cleaned_len) <= 0)
    {
        // 阻塞等待
    }

    // 获取接收缓冲区锁
    while (pthread_mutex_lock(&(sock->recv_lock)) != 0)
        ;

    int read_len = 0;
    // 确定读取长度
    if ((sock->received_len - sock->recv_cleaned_len) >= len)
    {
        read_len = len; // 读取请求长度的数据
    }
    else
    {
        read_len = (sock->received_len - sock->recv_cleaned_len); // 读取所有可用数据
    }

    // 复制数据到用户缓冲区
    memcpy(buffer, sock->received_buf, read_len);

    // 处理接收缓冲区剩余数据
    if (read_len < (sock->received_len - sock->recv_cleaned_len))
    {
        // 还有剩余数据，重新组织缓冲区
        char *new_buf = (char *)malloc(MAX_BUF_SIZE);
        memcpy(new_buf, sock->received_buf + read_len, sock->received_len - sock->recv_cleaned_len - read_len);
        free(sock->received_buf);
        sock->recv_cleaned_len += read_len;
        sock->received_buf = new_buf;
        sock->window.wnd_recv->wnd_available_size += read_len; // 更新接收窗口可用大小
    }
    else
    {
        // 所有数据都已读取，重置缓冲区
        free(sock->received_buf);
        sock->received_buf = (char *)malloc(MAX_BUF_SIZE);
        sock->recv_cleaned_len += read_len;
        sock->window.wnd_recv->wnd_available_size += read_len;
    }

    printf("tju_recv取出数据, 长度=%d, 已清理长度=%d\n", read_len, sock->recv_cleaned_len);

    pthread_mutex_unlock(&(sock->recv_lock)); // 释放锁

    return read_len;
}

// 处理接收到的TCP数据包
int tju_handle_packet(tju_tcp_t *sock, char *pkt)
{
    _RECV_LOG_(pkt);

    // 监听状态处理
    if (sock->state == LISTEN)
    {
        // 收到SYN包（第一次握手）
        if (get_flags(pkt) == SYN_FLAG_MASK)
        {
            // 发送SYN+ACK包（第二次握手）
            char *packet_SYN_ACK = create_packet_buf(get_dst(pkt), get_src(pkt), SERVER_ISN, get_seq(pkt) + 1,
                                                     DEFAULT_HEADER_LEN, DEFAULT_HEADER_LEN, (SYN_FLAG_MASK | ACK_FLAG_MASK), 1, 0, NULL, 0);
            sendToLayer3(packet_SYN_ACK, DEFAULT_HEADER_LEN);
            printf("监听状态收到SYN包，发送SYN+ACK包完成第二次握手\n");

            // 创建新连接并放入半连接队列
            tju_tcp_t *new_conn = (tju_tcp_t *)malloc(sizeof(tju_tcp_t));
            memcpy(new_conn, sock, sizeof(tju_tcp_t));
            new_conn->established_local_addr = new_conn->bind_addr;
            new_conn->established_remote_addr.ip = inet_network(CLIENT_IP);
            new_conn->established_remote_addr.port = get_src(pkt);
            new_conn->state = SYN_RECV;

            en_semi_conn_queue(new_conn, packet_SYN_ACK);
            printf("新连接进入SYN_RECV状态并加入半连接队列\n");
        }
        // 收到ACK包（第三次握手）
        else if (get_flags(pkt) == ACK_FLAG_MASK)
        {
            // 从半连接队列获取对应连接
            tju_tcp_t *tmp_conn = get_from_semi(pkt);
            printf("从半连接队列获取连接\n");
            if (tmp_conn == NULL)
            {
                printf("半连接队列中不存在该连接\n");
                return 0;
            }

            tmp_conn->state = ESTABLISHED;
            en_full_conn_queue(tmp_conn);
            printf("监听状态收到ACK包，连接进入全连接队列\n");
        }
    }
    // SYN_SENT状态处理（客户端）
    else if (sock->state == SYN_SENT)
    {
        // 收到SYN+ACK包（第二次握手）
        if (get_flags(pkt) == (SYN_FLAG_MASK | ACK_FLAG_MASK))
        {
            // 发送ACK包（第三次握手）
            char *packet_ACK = create_packet_buf(get_dst(pkt), get_src(pkt), get_ack(pkt), get_seq(pkt) + 1,
                                                 DEFAULT_HEADER_LEN, DEFAULT_HEADER_LEN, ACK_FLAG_MASK, 1, 0, NULL, 0);
            sendToLayer3(packet_ACK, DEFAULT_HEADER_LEN);
            sock->state = ESTABLISHED;
            free(packet_ACK);
            printf("SYN_SENT状态收到SYN+ACK包，发送ACK包完成第三次握手\n");
        }
    }
    // 已建立连接状态处理
    else if (sock->state == ESTABLISHED)
    {
        // 收到数据包
        if (get_flags(pkt) == NO_FLAG)
        {
            // 检查序列号是否匹配期望值
            if (get_seq(pkt) == sock->window.wnd_recv->expect_seq)
            {
                printf("收到数据包，序列号=%d\n", get_seq(pkt));
                uint16_t dlen = get_plen(pkt) - get_hlen(pkt);
                uint32_t expt_seq = sock->window.wnd_recv->expect_seq;
                uint32_t wnd_aval_size = sock->window.wnd_recv->wnd_available_size;

                // 检查接收窗口是否有足够空间
                if (get_seq(pkt) + dlen < expt_seq + wnd_aval_size)
                {
                    pthread_mutex_lock(&(sock->recv_lock));
                    // 将数据复制到接收缓冲区
                    memcpy(sock->received_buf + get_seq(pkt) - sock->recv_cleaned_len - 1, pkt + get_hlen(pkt), dlen);
                    uint32_t place = get_seq(pkt) - sock->recv_cleaned_len - 1;
                    printf("在接收缓冲区位置=%d放入数据，大小=%d\n", place, dlen);

                    // 更新接收窗口状态
                    sock->window.wnd_recv->wnd_available_size -= dlen;
                    sock->window.wnd_recv->expect_seq += dlen;
                    sock->received_len += dlen;

                    pthread_mutex_unlock(&(sock->recv_lock));
                    _DELV_LOG_(expt_seq, dlen);
                }

                // 发送ACK确认
                uint32_t ack = sock->window.wnd_recv->expect_seq;
                uint16_t adv_window = sock->window.wnd_recv->wnd_available_size;
                uint32_t seq = sock->window.wnd_send->nextseq;
                char *packet_ACK = create_packet_buf(sock->established_local_addr.port, sock->established_remote_addr.port, seq, ack,
                                                     DEFAULT_HEADER_LEN, DEFAULT_HEADER_LEN, ACK_FLAG_MASK, adv_window, 0, NULL, 0);
                sendToLayer3(packet_ACK, DEFAULT_HEADER_LEN);
                _SEND_LOG_(packet_ACK);
                free(packet_ACK);
            }
            else
            {
                // 序列号不匹配，发送期望的ACK
                uint32_t seq = sock->window.wnd_send->nextseq;
                uint32_t ack = sock->window.wnd_recv->expect_seq;
                uint16_t adv_window = sock->window.wnd_recv->wnd_available_size;
                char *packet_ACK = create_packet_buf(sock->established_local_addr.port, sock->established_remote_addr.port, seq, ack,
                                                     DEFAULT_HEADER_LEN, DEFAULT_HEADER_LEN, ACK_FLAG_MASK, adv_window, 0, NULL, 0);
                sendToLayer3(packet_ACK, DEFAULT_HEADER_LEN);
                _SEND_LOG_(packet_ACK);
                free(packet_ACK);
            }
        }
        // 收到ACK确认包
        else if (get_flags(pkt) == ACK_FLAG_MASK)
        {
            // 更新接收窗口大小
            sock->window.wnd_send->rwnd = get_advertised_window(pkt);
            _RWND_LOG_(sock);

            // 检查ACK是否在窗口内
            if (get_ack(pkt) < sock->window.wnd_send->base)
            {
                printf("收到的ACK报文在发送窗口外，丢弃报文\n");
                sock->window.wnd_send->window_size = min(sock->window.wnd_send->cwnd, sock->window.wnd_send->rwnd);
                _SWND_LOG_(sock);
            }
            // 收到重复ACK
            else if (get_ack(pkt) == sock->window.wnd_send->base)
            {
                printf("收到重复ACK报文 ack=%d\n", get_ack(pkt));

                // 拥塞控制处理
                if (sock->window.wnd_send->congestion_status == SLOW_START || sock->window.wnd_send->congestion_status == CONGESTION_AVOIDANCE)
                {
                    sock->window.wnd_send->same_ack_cnt++;
                }
                else if (sock->window.wnd_send->congestion_status == FAST_RECOVERY)
                {
                    sock->window.wnd_send->cwnd = min(sock->window.wnd_send->cwnd + MAX_DLEN, MAX_BUF_SIZE);
                    _CWND_LOG_(sock, FAST_RECOVERY);
                }

                // 快速重传触发条件
                if (sock->window.wnd_send->same_ack_cnt == 3 && sock->window.wnd_send->congestion_status != FAST_RECOVERY)
                {
                    sock->window.wnd_send->ssthresh = max(sock->window.wnd_send->cwnd >> 1, 2 * MAX_DLEN);
                    sock->window.wnd_send->cwnd = (sock->window.wnd_send->ssthresh + 3 * MAX_DLEN);
                    _CWND_LOG_(sock, FAST_RECOVERY);
                    sock->window.wnd_send->congestion_status = FAST_RECOVERY;
                    printf("收到三个重复ACK，开始快速重传, 拥塞窗口=%d, 慢启动阈值=%d\n", sock->window.wnd_send->cwnd, sock->window.wnd_send->ssthresh);
                    RETRANS = TRUE;
                }
                sock->window.wnd_send->window_size = min(sock->window.wnd_send->cwnd, sock->window.wnd_send->rwnd);
                _SWND_LOG_(sock);
            }
            // 收到有效ACK
            else
            {
                printf("收到有效ACK报文 ack=%d\n", get_ack(pkt));
                sock->window.wnd_send->same_ack_cnt = 0;

                // 拥塞控制状态更新
                if (sock->window.wnd_send->congestion_status == SLOW_START)
                {
                    sock->window.wnd_send->cwnd *= 2;
                    if (sock->window.wnd_send->cwnd >= sock->window.wnd_send->ssthresh)
                    {
                        sock->window.wnd_send->cwnd = sock->window.wnd_send->ssthresh;
                        sock->window.wnd_send->congestion_status = CONGESTION_AVOIDANCE;
                    }
                    _CWND_LOG_(sock, SLOW_START);
                }
                else if (sock->window.wnd_send->congestion_status == CONGESTION_AVOIDANCE)
                {
                    sock->window.wnd_send->cwnd += MAX_DLEN;
                    if (sock->window.wnd_send->cwnd > MAX_BUF_SIZE)
                    {
                        sock->window.wnd_send->cwnd = MAX_BUF_SIZE;
                    }
                    _CWND_LOG_(sock, CONGESTION_AVOIDANCE);
                }
                else if (sock->window.wnd_send->congestion_status == FAST_RECOVERY)
                {
                    sock->window.wnd_send->cwnd = sock->window.wnd_send->ssthresh;
                    sock->window.wnd_send->congestion_status = CONGESTION_AVOIDANCE;
                    _CWND_LOG_(sock, CONGESTION_AVOIDANCE);
                }

                // 更新发送窗口大小
                sock->window.wnd_send->window_size = min(sock->window.wnd_send->cwnd, sock->window.wnd_send->rwnd);
                _SWND_LOG_(sock);

                // RTT估计处理
                if (sock->window.wnd_send->is_estimating_RTT == TRUE)
                {
                    if (sock->window.wnd_send->rtt_expect_ack == get_ack(pkt))
                    {
                        long sampleRTT = Caltimeout(sock);
                    }
                    sock->window.wnd_send->is_estimating_RTT = FALSE;
                }

                // 更新发送窗口基序号
                sock->window.wnd_send->base = get_ack(pkt);
                sock->window.wnd_send->ack_cnt = sock->window.wnd_send->base - 1;

                // 检查发送队列状态
                if (sock->window.wnd_send->base == sock->window.wnd_send->nextseq)
                {
                    stopTimer();
                    printf("发送队列完成\n");
                }
                else
                {
                    startTimer(sock);
                }

                // 清理已确认的发送缓冲区数据
                if (sock->window.wnd_send->ack_cnt - sock->send_cleaned_len > 0)
                {
                    pthread_mutex_lock(&sock->send_lock);
                    char *new_sending_buf = (char *)malloc(MAX_BUF_SIZE);
                    memcpy(new_sending_buf, sock->sending_buf + sock->window.wnd_send->ack_cnt - sock->send_cleaned_len, sock->sending_len - sock->window.wnd_send->ack_cnt);
                    free(sock->sending_buf);
                    sock->sending_buf = new_sending_buf;
                    sock->send_cleaned_len = sock->window.wnd_send->ack_cnt;
                    pthread_mutex_unlock(&sock->send_lock);
                }
            }

            // 处理零窗口情况
            if (sock->window.wnd_send->window_size == 0)
            {
                printf("开启零窗口定时器: 拥塞窗口=%d  接收窗口=%d\n", sock->window.wnd_send->cwnd, sock->window.wnd_send->rwnd);
                startTimer(sock);
                RETRANS = FALSE;
                return 0;
            }
        }
        // 收到FIN包（开始连接关闭）
        else if (get_flags(pkt) == FIN_FLAG_MASK)
        {
            // 发送ACK确认
            uint32_t ack = get_seq(pkt) + 1;
            char *packet_ACK = create_packet_buf(get_dst(pkt), get_src(pkt), get_ack(pkt), ack,
                                                 DEFAULT_HEADER_LEN, DEFAULT_HEADER_LEN, ACK_FLAG_MASK, 1, 0, NULL, 0);
            sendToLayer3(packet_ACK, DEFAULT_HEADER_LEN);

            sock->state = CLOSE_WAIT;
            printf("已建立连接状态收到FIN包，发送ACK并进入CLOSE_WAIT状态，完成第二次挥手\n");
            free(packet_ACK);

            sleep(1); // 等待数据传输完成

            // 发送FIN+ACK包
            char *packet_FIN_ACK = create_packet_buf(sock->established_local_addr.port, sock->established_remote_addr.port, FIN_SEQ,
                                                     ack, DEFAULT_HEADER_LEN, DEFAULT_HEADER_LEN, (FIN_FLAG_MASK | ACK_FLAG_MASK), 1, 0, NULL, 0);
            sendToLayer3(packet_FIN_ACK, DEFAULT_HEADER_LEN);
            sock->packet_FIN = packet_FIN_ACK;
            sock->state = LAST_ACK;
            printf("CLOSE_WAIT状态发送FIN+ACK包并进入LAST_ACK状态，完成第三次挥手\n");

            // 创建关闭线程处理重传
            pthread_t id;
            int rst = pthread_create(&id, NULL, tju_close_thread, (void *)sock);
            if (rst < 0)
            {
                printf("错误：无法创建关闭线程\n");
                exit(-1);
            }
        }
    }
    // FIN_WAIT_1状态处理
    else if (sock->state == FIN_WAIT_1)
    {
        // 收到ACK确认
        if (get_flags(pkt) == ACK_FLAG_MASK)
        {
            sock->state = FIN_WAIT_2;
            printf("进入FIN_WAIT_2状态\n");
        }
        // 同时关闭情况：收到FIN包
        else if (get_flags(pkt) == FIN_FLAG_MASK)
        {
            // 发送ACK确认
            char *packet_ACK = create_packet_buf(get_dst(pkt), get_src(pkt), FIN_SEQ + 1, get_seq(pkt) + 1,
                                                 DEFAULT_HEADER_LEN, DEFAULT_HEADER_LEN, ACK_FLAG_MASK, 1, 0, NULL, 0);
            sendToLayer3(packet_ACK, DEFAULT_HEADER_LEN);
            free(packet_ACK);
            sock->state = CLOSING;
            printf("FIN_WAIT_1状态同时收到FIN包，进入CLOSING状态\n");
        }
        // 收到FIN+ACK包
        else if (get_flags(pkt) == (FIN_FLAG_MASK | ACK_FLAG_MASK))
        {
            char *packet_ACK = create_packet_buf(get_dst(pkt), get_src(pkt), FIN_SEQ + 1, get_seq(pkt) + 1,
                                                 DEFAULT_HEADER_LEN, DEFAULT_HEADER_LEN, ACK_FLAG_MASK, 1, 0, NULL, 0);
            sendToLayer3(packet_ACK, DEFAULT_HEADER_LEN);
            free(packet_ACK);
            sock->state = TIME_WAIT;
            printf("收到FIN+ACK包，发送ACK并进入TIME_WAIT状态，等待2MSL\n");
            sleep(2);
            sock->state = CLOSED;
        }
    }
    // FIN_WAIT_2状态处理
    else if (sock->state == FIN_WAIT_2)
    {
        // 收到FIN+ACK包
        if (get_flags(pkt) == (FIN_FLAG_MASK | ACK_FLAG_MASK))
        {
            // 发送ACK确认
            char *packet_ACK = create_packet_buf(get_dst(pkt), get_src(pkt), get_ack(pkt), get_seq(pkt) + 1,
                                                 DEFAULT_HEADER_LEN, DEFAULT_HEADER_LEN, ACK_FLAG_MASK, 1, 0, NULL, 0);
            sendToLayer3(packet_ACK, DEFAULT_HEADER_LEN);
            free(packet_ACK);
            sock->state = TIME_WAIT;
            printf("FIN_WAIT_2状态收到FIN+ACK包，发送ACK并进入TIME_WAIT状态，等待2MSL后关闭，完成第四次挥手\n");
            sleep(2);
            sock->state = CLOSED;
            printf("连接关闭\n");
        }
    }
    // LAST_ACK状态处理（服务器端）
    else if (sock->state == LAST_ACK)
    {
        // 收到ACK确认
        if (get_flags(pkt) == ACK_FLAG_MASK)
        {
            printf("LAST_ACK状态收到ACK包，连接关闭\n");
            sock->state = CLOSED;
        }
    }
    // CLOSING状态处理（同时关闭）
    else if (sock->state == CLOSING)
    {
        // 收到ACK确认
        if (get_flags(pkt) == ACK_FLAG_MASK && get_ack(pkt) == FIN_SEQ + 1)
        {
            sock->state = TIME_WAIT;
            printf("CLOSING状态收到ACK包，进入TIME_WAIT状态，等待2MSL后关闭\n");
            sleep(2);
            sock->state = CLOSED;
            printf("连接关闭\n");
        }
    }

    return 0;
}

void *tju_close_thread(void *arg)
{
    tju_tcp_t *sock = (tju_tcp_t *)arg;
    tju_close(sock);
}

int tju_close(tju_tcp_t *sock)
{
    clock_t time_point;
    // 根据当前连接状态处理关闭流程
    if (sock->state == ESTABLISHED)
    {
        // 构造并发送FIN报文，启动四次挥手
        char *packet_FIN = create_packet_buf(sock->established_local_addr.port, sock->established_remote_addr.port,
                                             FIN_SEQ, 0, DEFAULT_HEADER_LEN, DEFAULT_HEADER_LEN,
                                             FIN_FLAG_MASK, 1, 0, NULL, 0);
        sendToLayer3(packet_FIN, DEFAULT_HEADER_LEN);
        sock->packet_FIN = packet_FIN;
        time_point = clock();
        sock->state = FIN_WAIT_1; // 进入FIN_WAIT_1状态
        printf("客户端在ESTABLISHED状态发送FIN，进入FIN_WAIT_1状态 ---- 第一次挥手完成\n");
    }
    else if (sock->state == LAST_ACK)
    {
        time_point = clock();
    }
    else
    {
        printf("关闭套接字时状态错误\n");
        exit(-1);
    }

    // 阻塞等待连接完全关闭，期间处理超时重传
    printf("等待中......\n");
    while (sock->state != CLOSED)
    {
        // 超时重传FIN报文（8秒超时）
        if ((clock() - time_point) >= 8000000)
        {
            sendToLayer3(sock->packet_FIN, DEFAULT_HEADER_LEN);
            printf("超时，重发FIN报文\n");
            time_point = clock();
        }
    }

    printf("连接已关闭\n");

    // 清理连接信息
    int hashval = cal_hash(sock->established_local_addr.ip, sock->established_local_addr.port,
                           sock->established_remote_addr.ip, sock->established_remote_addr.port);
    established_socks[hashval] = NULL;
    free(sock->packet_FIN);
    free(sock);
    close_log();
    return 0;
}

// 生成一个随机端口号（范围：3333-13333）
uint16_t generate_port()
{
    srand((unsigned int)time(NULL));
    uint16_t port = rand() % 10001 + 3333;
    return port;
}

void *sending_thread(void *arg)
{
    tju_tcp_t *sock = (tju_tcp_t *)arg; // 获取发送方套接字

    // 持续处理发送任务
    while (1)
    {
        // 满足发送条件：有未发送数据、发送窗口有空闲空间、不在重传状态
        if ((sock->window.wnd_send->nextseq <= sock->sending_len) &&
            ((sock->window.wnd_send->nextseq - sock->window.wnd_send->base) < sock->window.wnd_send->window_size) &&
            !RETRANS)
        {
            pthread_mutex_lock(&sock->send_lock); // 加锁保证线程安全

            int dlen;      // 数据长度
            uint16_t plen; // 数据包总长度（头部+数据）
            uint32_t wnd_size = sock->window.wnd_send->window_size;
            uint32_t wnd_next_seq = sock->window.wnd_send->nextseq;
            uint32_t wnd_base = sock->window.wnd_send->base;

            // 计算本次可发送的数据长度：取未发送数据量和窗口剩余空间的较小值
            uint32_t data_send_len = min(sock->sending_len - wnd_next_seq + 1,
                                         wnd_size - (wnd_next_seq - wnd_base));
            // 定位发送数据在缓冲区中的位置
            char *data = sock->sending_buf + (wnd_next_seq - sock->send_cleaned_len - 1);

            // 数据长度小于等于最大允许长度，无需分包
            if (data_send_len <= MAX_DLEN)
            {
                dlen = data_send_len;
                plen = dlen + DEFAULT_HEADER_LEN;
                // 构造并发送数据包
                char *packet1 = create_packet_buf(sock->established_local_addr.port,
                                                  sock->established_remote_addr.port,
                                                  wnd_next_seq, 0, DEFAULT_HEADER_LEN, plen,
                                                  NO_FLAG, 1, 0, data, dlen);
                sendToLayer3(packet1, plen);
                _SEND_LOG_(packet1);
                free(packet1);
                printf("发送数据 seq = %d, 数据长度 = %d\n", wnd_next_seq, dlen);
                data_send_len = 0;

                // 启动RTT估算（如未启动）
                if (sock->window.wnd_send->is_estimating_RTT == FALSE)
                {
                    sock->window.wnd_send->is_estimating_RTT = TRUE;
                    gettimeofday(&sock->window.wnd_send->send_time, NULL);
                    sock->window.wnd_send->rtt_expect_ack = wnd_next_seq + dlen;
                }

                // 若为窗口内第一个数据包，启动计时器
                if (wnd_base == wnd_next_seq)
                    startTimer(sock);

                wnd_next_seq += dlen; // 更新下一个发送序列号
            }
            // 数据过长，需要分包发送
            else
            {
                // 循环发送直到所有数据发送完毕
                while (data_send_len > 0)
                {
                    dlen = (data_send_len > MAX_DLEN) ? MAX_DLEN : data_send_len;
                    plen = dlen + DEFAULT_HEADER_LEN;

                    // 构造并发送当前分包
                    char *packet2 = create_packet_buf(sock->established_local_addr.port,
                                                      sock->established_remote_addr.port,
                                                      wnd_next_seq, 0, DEFAULT_HEADER_LEN, plen,
                                                      NO_FLAG, 1, 0, data, dlen);
                    sendToLayer3(packet2, plen);
                    _SEND_LOG_(packet2);
                    free(packet2);
                    printf("发送数据 seq = %d, 数据长度 = %d\n", wnd_next_seq, dlen);

                    // 启动RTT估算（如未启动）
                    if (sock->window.wnd_send->is_estimating_RTT == FALSE)
                    {
                        sock->window.wnd_send->is_estimating_RTT = TRUE;
                        gettimeofday(&sock->window.wnd_send->send_time, NULL);
                        sock->window.wnd_send->rtt_expect_ack = wnd_next_seq + dlen;
                    }

                    // 若为窗口内第一个数据包，启动计时器
                    if (wnd_base == wnd_next_seq)
                        startTimer(sock);

                    // 更新剩余数据长度、数据指针和下一个发送序列号
                    data_send_len -= dlen;
                    data += dlen;
                    wnd_next_seq += dlen;
                }
            }

            sock->window.wnd_send->nextseq = wnd_next_seq; // 更新发送窗口的下一个序列号
            pthread_mutex_unlock(&sock->send_lock);        // 解锁
        }
    }
}

// 超时重传线程
void *retrans_thread(void *arg)
{
    tju_tcp_t *sock = (tju_tcp_t *)arg;
    while (1)
    {
        // 检查是否需要重传
        if (RETRANS)
        {
            pthread_mutex_lock(&(sock->send_lock));
            // 处理超时情况
            if (TIMEOUT_FLAG)
            {
                // 拥塞控制调整
                sock->window.wnd_send->ssthresh = max(sock->window.wnd_send->cwnd >> 1, 2 * MAX_DLEN);
                sock->window.wnd_send->cwnd = MAX_DLEN;
                _CWND_LOG_(sock, TIME_OUT);
                sock->window.wnd_send->same_ack_cnt = 0;
                sock->window.wnd_send->congestion_status = SLOW_START;
                sock->window.wnd_send->window_size = min(sock->window.wnd_send->cwnd, sock->window.wnd_send->rwnd);
                _SWND_LOG_(sock);
                TIMEOUT_FLAG = FALSE;
            }

            uint32_t wnd_base = sock->window.wnd_send->base;
            uint32_t wnd_next_seq = sock->window.wnd_send->nextseq;
            uint32_t wnd_ack = sock->window.wnd_send->ack_cnt;

            // 重传所有未确认的数据
            while (wnd_base < wnd_next_seq)
            {
                uint32_t dlen;
                char *data = sock->sending_buf + wnd_ack - sock->send_cleaned_len;

                // 处理剩余数据小于最大分组长度的特殊情况
                if ((wnd_next_seq - wnd_base) < MAX_DLEN)
                {
                    dlen = wnd_next_seq - wnd_base;
                    char *packet1 = create_packet_buf(sock->established_local_addr.port, sock->established_remote_addr.port, wnd_base, 0,
                                                      DEFAULT_HEADER_LEN, DEFAULT_HEADER_LEN + dlen, NO_FLAG, 1, 0, data, dlen);
                    sendToLayer3(packet1, DEFAULT_HEADER_LEN + dlen);
                    _SEND_LOG_(packet1);
                    free(packet1);
                    printf("重传数据 seq = %d, 数据长度 = %d\n", wnd_base, dlen);
                }
                else
                {
                    dlen = MAX_DLEN;
                    char *packet2 = create_packet_buf(sock->established_local_addr.port, sock->established_remote_addr.port, wnd_base, 0,
                                                      DEFAULT_HEADER_LEN, DEFAULT_HEADER_LEN + dlen, NO_FLAG, 1, 0, data, dlen);
                    sendToLayer3(packet2, DEFAULT_HEADER_LEN + dlen);
                    _SEND_LOG_(packet2);
                    free(packet2);
                    printf("重传数据 seq = %d, 数据长度 = %d\n", wnd_base, dlen);
                }

                if (wnd_base == sock->window.wnd_send->base)
                    startTimer(sock);
                wnd_base += dlen;
                wnd_ack += dlen;
            }

            RETRANS = FALSE;
            pthread_mutex_unlock(&(sock->send_lock));
        }
    }
}

// 超时处理函数
void timeout_handler(int signo)
{
    RETRANS = TRUE;
    TIMEOUT_FLAG = TRUE;
}

// 启动定时器
void startTimer(tju_tcp_t *sock)
{
    struct itimerval tick;
    RETRANS = FALSE;
    TIMEOUT_FLAG = FALSE;

    memset(&tick, 0, sizeof(tick));
    memcpy(&tick, &sock->window.wnd_send->timeout, sizeof(tick));

    if (setitimer(ITIMER_REAL, &tick, NULL) < 0)
    {
        printf("设置定时器失败!\n");
    }
}

// 停止定时器
void stopTimer(void)
{
    struct itimerval value;
    value.it_value.tv_sec = 0;
    value.it_value.tv_usec = 0;
    value.it_interval.tv_sec = 0;
    value.it_interval.tv_usec = 0;
    setitimer(ITIMER_REAL, &value, NULL);
}

// 计算窗口移动长度
uint16_t get_wnd_move_len(uint8_t *mark)
{
    uint16_t ans = 0;
    while (mark[ans] != 0)
    {
        ans++;
    }
    return ans;
}

// 计算超时时间
int Caltimeout(tju_tcp_t *sock)
{
    struct timeval send_time = sock->window.wnd_send->send_time;
    struct timeval local_time;
    gettimeofday(&local_time, NULL);
    long sampleRTT = (local_time.tv_sec - send_time.tv_sec) * 1000000 + (local_time.tv_usec - send_time.tv_usec);

    // 更新平滑RTT和偏差值
    sock->window.wnd_send->SRTT = ALPHA * sock->window.wnd_send->SRTT + (1 - ALPHA) * sampleRTT;
    sock->window.wnd_send->dev_rtt = BETA * sock->window.wnd_send->dev_rtt + (1 - BETA) * sampleRTT;

    // 计算新的超时时间，确保在合理范围内
    sock->window.wnd_send->timeout.it_value.tv_usec = min(UBPUND * 1000000, max(LBOUND * 1000000, sock->window.wnd_send->SRTT + 4 * sock->window.wnd_send->dev_rtt));
    _RTTS_LOG_(sock, sampleRTT);
    return sampleRTT;
}

// 初始化日志系统
void init_log()
{
    server_event_log = fopen("./server.event.trace", "w");
    client_event_log = fopen("./client.event.trace", "w");
}

// 关闭日志系统
void close_log()
{
    fclose(server_event_log);
    fclose(client_event_log);
}

// 获取当前时间（微秒）
long getCurrentTime()
{
    struct timeval tv;
    gettimeofday(&tv, NULL);
    long time = (tv.tv_sec - start.tv_sec) * 1000000 + (tv.tv_usec - start.tv_usec);
    return time;
}

// 获取当前主机的日志文件指针
FILE *getEventlog()
{
    char hostname[8];
    gethostname(hostname, 8);
    if (strcmp(hostname, "server") == 0)
        return server_event_log;
    else if (strcmp(hostname, "client") == 0)
        return client_event_log;
    else
    {
        printf("获取事件日志失败：无法识别主机名\n");
        exit(-1);
    }
}